/*
 * Copyright (c) 2013, SRI International
 * All rights reserved.
 * Licensed under the The BSD 3-Clause License;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 * 
 * http://opensource.org/licenses/BSD-3-Clause
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of the aic-web-praise nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.sri.ai.lpitools.gwtgui.client.components.graphpanel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.ChartArea;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.LegendPosition;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.visualizations.corechart.AxisOptions;
import com.google.gwt.visualization.client.visualizations.corechart.BarChart;
import com.google.gwt.visualization.client.visualizations.corechart.ColumnChart;
import com.google.gwt.visualization.client.visualizations.corechart.Options;
import com.google.gwt.visualization.client.visualizations.corechart.PieChart;

public class SRIGraphPanel extends CaptionPanel {

	private List<String> titles;
	private List<Double> values;

	/**
	 * GraphPanel constructor that takes in the title for the panel
	 * @param title
	 */
	public SRIGraphPanel(String title){
		super(title);
		titles = new ArrayList<String>();
		values = new ArrayList<Double>();
		
	}
	/**
	 * Function that add graph to the screen
	 */
	public void addGraph(){
		Runnable onLoadCallback = new Runnable() {
			public void run() {
				// Create a chart visualization.
				BarChart chart = new BarChart(createTable(), createOptions());
				add(chart);
			}
		};
		// Load the visualization api, passing the onLoadCallback to be called
		// when loading is done.
		VisualizationUtils.loadVisualizationApi(onLoadCallback, BarChart.PACKAGE);		
	}
	/**
	 * Function that add graph to the screen
	 */
	public void addColumnGraph(){
		Runnable onLoadCallback = new Runnable() {
			public void run() {
				// Create a chart visualization.
				ColumnChart chart = new ColumnChart(createTable(), createOptionsColumn());
				add(chart);
			}
		};
		// Load the visualization api, passing the onLoadCallback to be called
		// when loading is done.
		VisualizationUtils.loadVisualizationApi(onLoadCallback, BarChart.PACKAGE);		
	}
	
	/**
	 * Function to add a pie graph to the screen
	 */
	public void addPieGraph(){
	    Runnable onLoadCallback = new Runnable() {
	        public void run() {	          	   
	        	// Create a pie chart visualization.
	        	PieChart chart = new PieChart(createTable(), createOptions());
	        	add(chart);
	        }
	      };
	      // Load the visualization api, passing the onLoadCallback to be called
	      // when loading is done.
	      VisualizationUtils.loadVisualizationApi(onLoadCallback, PieChart.PACKAGE);	
	}
	
	/**
	 * function to add a row of data to the data table
	 * @param title
	 * @param valueSecond
	 */
	public void addRow(String title, double valueSecond){
		titles.add(title);
		values.add(valueSecond);
	}
	
	/**
	 * Function to add multiple rows to the data table
	 * @param titles
	 * @param values
	 */
	public void addRows(List<String> titles, List<Double> values){
		this.titles.addAll(titles);
		this.values.addAll(values);		
	}

	/**
	 * Function to add multiple rows to the data table
	 * @param titles
	 * @param values
	 */
	public void addRows(List<ResultModel> list){
		ResultModelComparator rc = new ResultModelComparator();
		Collections.sort(list, rc);
		int max = 10;
		if(list.size() <= 10) {
			max = list.size();
		}
		for(int i = 0; i<max; i++){
			int index  = (list.size() - 1) -i;
			this.titles.add(list.get(index).getName());
			this.values.add(list.get(index).getValue());			
		}
	}
	
	/**
	 * Function to set options for graph
	 * @return
	 */
	private Options createOptions() {
		Options options = Options.create();
	    options.setWidth(600);
	    options.setHeight(600);
	    ChartArea chartArea = ChartArea.create();
	    chartArea.setWidth(175);
	    chartArea.setTop(10);
	    options.setChartArea(chartArea);
	    options.setLegend(LegendPosition.NONE);
	    
		return options;
	}
	
	/**
	 * Function to set options for graph
	 * @return
	 */
	private Options createOptionsColumn() {
		AxisOptions optionsH = AxisOptions.create();
		optionsH.set("slantedText", true);
		optionsH.set("slantedTextAngle", 60.0);

		Options options = Options.create();
	    options.setWidth(600);
	    options.setHeight(600);
	    AxisOptions vAxisOptions = AxisOptions.create();
	    vAxisOptions.setMinValue(0);

	    options.setVAxisOptions(vAxisOptions);
	    options.setHAxisOptions(optionsH);
	    ChartArea chartArea = ChartArea.create();
	    chartArea.setHeight(200);
	    chartArea.setTop(10);
	    options.setChartArea(chartArea);
	    options.setLegend(LegendPosition.NONE);
		return options;
	}

	/**
	 * Function that creates the datatable
	 * @return
	 */
	private DataTable createTable() {
			int size = titles.size();
			DataTable data = DataTable.create();
			
		    data.addColumn(ColumnType.STRING, "Task");
		    data.addColumn(ColumnType.NUMBER, "Precentage of the Total Time to run Query for this step to execute");
		    data.addRows(size);
		    for(int i = 0; i<titles.size(); i++){
		    	data.setValue(i, 0, titles.get(i));
		    }
		    double sum = sumValues();
		    List<Double> pValues = precentValues(sum);
		    for(int i = 0; i<pValues.size(); i++){
		    	data.setValue(i, 1, pValues.get(i));
		    }		    
		    return data;
	}
	
	private double sumValues(){
		double sum = 0;
	    for(int i = 0; i<values.size(); i++){
	    	sum = sum+ values.get(i);
	    }
	    return sum;
	}
	
	private List<Double> precentValues(double sum){
		
		List<Double> pValues = new ArrayList<Double>();
	    for(int i = 0; i<values.size(); i++){
	    	double p = (values.get(i)/sum) * 100;
	    	pValues.add(p);
	    }
	    return pValues;
	}
	
	public void clearData(){
		titles = new ArrayList<String>();
		values = new ArrayList<Double>();		
	}

}
